package com.gudy.engine.handler.pub;

import com.gudy.engine.bean.EngineConfig;
import com.gudy.engine.bean.command.RbCmd;
import com.gudy.engine.bean.orderbook.MatchEvent;
import com.gudy.engine.handler.risk.BaseHandler;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.collections4.CollectionUtils;
import org.eclipse.collections.api.tuple.primitive.ShortObjectPair;
import org.eclipse.collections.impl.map.mutable.primitive.IntObjectHashMap;
import org.eclipse.collections.impl.map.mutable.primitive.ShortObjectHashMap;
import thirdpart.bean.CommonMsg;
import thirdpart.hq.L1MarketData;
import thirdpart.hq.MatchData;
import thirdpart.order.CmdType;

import java.util.List;

import static thirdpart.bean.MsgConstants.*;

@Log4j2
@RequiredArgsConstructor
public class L1PubHandler extends BaseHandler {

    public static final int HQ_PUB_RATE=5000;

    /**缓存要发个每个柜台的数据*/
    @NonNull
    private final ShortObjectHashMap<List<MatchData>> matchEventMap;

    @NonNull
    private EngineConfig config;

    @Override
    public void onEvent(RbCmd cmd, long sequence, boolean endOfBatch) throws Exception {
        final CmdType cmdType = cmd.command;

        if(cmdType == CmdType.NEW_ORDER || cmdType == CmdType.CANCEL_ORDER){
            for(MatchEvent e:cmd.matchEventList){
                matchEventMap.get(e.mid).add(e.copy());
            }
        }else if(cmdType == CmdType.HQ_PUB){
            //1 五档行情 给所有柜台都发
            pubMarketData(cmd.marketDataMap);
            //2 给某个柜台发送MatchData
            pubMarketData();
        }
    }

    private void pubMarketData() {
        if(matchEventMap.size() == 0){
            return;
        }
        log.info(matchEventMap);

        try{
            for (ShortObjectPair<List<MatchData>> s : matchEventMap.keyValuesView()) {
                if(CollectionUtils.isEmpty(s.getTwo())){
                    continue;
                }
                byte[] serialize = config.getBodyCodec().serialize(s.getTwo().toArray(new MatchData[0]));
                pubData(serialize,s.getOne(),MATCH_ORDER_DATA);

                //清空已发送数据
                s.getTwo().clear();
            }
        }catch (Exception e){
            log.error(e);
        }
    }

    public static final short HQ_ADDRESS = -1;
    private void pubMarketData(IntObjectHashMap<L1MarketData> marketDataMap) {
        byte[] serialize = null;
        try {
            serialize = config.getBodyCodec().serialize(marketDataMap.values().toArray(new L1MarketData[0]));
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(serialize == null){
            return;
        }
        pubData(serialize,HQ_ADDRESS,MATCH_HQ_DATA);
    }

    private void pubData(byte[] serialize, short dst, short msgType) {
        CommonMsg msg = new CommonMsg();
        msg.setBodyLength(serialize.length);
        msg.setChecksum(config.getCs().getCheckSum(serialize));
        msg.setMsgSrc(config.getId());
        msg.setMsgDst(dst);
        msg.setMsgType(msgType);
        msg.setStatus(NORMAL);
        msg.setBody(serialize);
        config.getBusSender().publish(msg);
    }

}
